package com.bank.bank.transaction.service.impl;


import com.bank.bank.common.base.exception.ServiceException;
import com.bank.bank.common.base.pojo.dto.AccountDTO;
import com.bank.bank.common.base.pojo.dto.DrawMoneyParam;
import com.bank.bank.common.base.pojo.dto.SaveMoneyParam;
import com.bank.bank.common.base.pojo.dto.TransferMoneyParam;
import com.bank.bank.common.base.pojo.entity.Transaction;
import com.bank.bank.common.base.pojo.vo.DrawMoneyVO;
import com.bank.bank.common.base.pojo.vo.SaveMoneyVO;
import com.bank.bank.common.base.pojo.vo.TransactionDetailVO;
import com.bank.bank.common.base.response.JsonResult;
import com.bank.bank.common.base.response.StatusCode;
import com.bank.bank.transaction.client.AccountClient;
import com.bank.bank.transaction.mapper.TransactionMapper;
import com.bank.bank.transaction.service.TransactionService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;

/**
 * Transactional注解: 事务注解;
 */
@Slf4j
@Service
@Transactional
public class TransactionServiceImpl implements TransactionService {
    @Autowired
    private TransactionMapper transactionMapper;
    @Autowired
    private AccountClient accountClient;
    /**
     * 1.存款业务
     * @param saveMoneyParam to_account_id、amount
     * @return
     */
    @Override
    public SaveMoneyVO deposit(SaveMoneyParam saveMoneyParam) {
        log.debug("存款业务:saveMoneyParam={}", saveMoneyParam);
        //1.存入数据[mapper层接口-交易表中]
        Transaction transaction = new Transaction();
        BeanUtils.copyProperties(saveMoneyParam, transaction);
        transaction.setType("DEPOSIT");
        transaction.setCreatedAt(new Date());
        transactionMapper.saveMoneyInsertTransaction(transaction);
        //2.封装一下更新账户查询的方法
        JsonResult jsonResult = accountClient.updateAndGetAccounts
                (saveMoneyParam.getToAccountId(), saveMoneyParam.getAmount());
        Object data = jsonResult.getData();
        if (data!=null){
            LinkedHashMap auVo=(LinkedHashMap)data;
            SaveMoneyVO vo=new SaveMoneyVO();
            vo.setType("DEPOSIT");
            vo.setToAccountNumber((String)auVo.get("toAccountNumber"));
            vo.setNewBalance((Double)auVo.get("newBalance"));
            vo.setTransactionId(transaction.getId());
            vo.setAmount(saveMoneyParam.getAmount());
            vo.setCreatedAt(transaction.getCreatedAt());
            return vo;
        }else{
            throw new RuntimeException("更新账户余额失败");
        }
    }

    /**
     * 2.取款功能业务
     * @param drawMoneyParam
     * @return
     */
    @Override
    public DrawMoneyVO withdraw(DrawMoneyParam drawMoneyParam) {
        log.debug("取款功能业务:drawMoneyParam={}", drawMoneyParam);
        //1.查询余额,进行判断; 远程调用
        Integer fromAccountId = drawMoneyParam.getFromAccountId();
        Double amount = drawMoneyParam.getAmount();
        //2.远程调用拿到账号详情
        AccountDTO accountDTO = accountClient.getAccountById(fromAccountId);
        Double balance = accountDTO.getBalance();
        /*Double balance = transactionMapper.selectBalanceByFromAccountId(fromAccountId);*/
        if (balance < amount) {//余额不足
            throw new ServiceException(StatusCode.MONEY_NOT_ENOUGH);
        }
        //2.交易表中插入交易记录;
        Transaction transaction = new Transaction();
        BeanUtils.copyProperties(drawMoneyParam, transaction);
        transaction.setType("WITHDRAW");
        transaction.setCreatedAt(new Date());
        transactionMapper.saveMoneyInsertTransaction(transaction); //复用存款的方法;
        //调用一个更新amount 复用方法
        /*//3.账户表中更新账户余额;
        transactionMapper.drawMoneyUpdateTransactionByFromAccountId(drawMoneyParam);
        //4.查询最新交易信息;
        DrawMoneyVO drawMoneyVO = transactionMapper.drawMoneySelectTransactionInfo(transaction);*/
        JsonResult jsonResult = accountClient.updateAndGetAccounts(fromAccountId, -amount);
        Object data = jsonResult.getData();
        if (data!=null){
            LinkedHashMap auVo=(LinkedHashMap)data;
            DrawMoneyVO vo=new DrawMoneyVO();
            vo.setType("WITHDRAW");
            vo.setFromAccountNumber((String)auVo.get("toAccountNumber"));
            vo.setNewBalance((Double)auVo.get("newBalance"));
            vo.setTransactionId(transaction.getId());
            vo.setAmount(drawMoneyParam.getAmount());
            vo.setCreatedAt(transaction.getCreatedAt());
            return vo;
        }else{
            throw new RuntimeException("更新账户余额失败");
        }
    }

    /**
     * 3.转账功能
     * @param transferMoneyParam
     */
    @Override
    public void transfer(TransferMoneyParam transferMoneyParam) {
        log.debug("转账业务:transferMoneyParam={}", transferMoneyParam);
        //1.查询源账户余额from_account_id,并进行判断;
        Integer fromAccountId = transferMoneyParam.getFromAccountId();
        Integer toAccountId= transferMoneyParam.getToAccountId();
        Double amount = transferMoneyParam.getAmount();
        /*Double balance = transactionMapper.selectBalanceByFromAccountId(fromAccountId); 检查from的余额*/
        AccountDTO accountDTO = accountClient.getAccountById(fromAccountId);
        Double balance = accountDTO.getBalance();
        if (balance < amount) {
            throw new ServiceException(StatusCode.MONEY_NOT_ENOUGH);
        }

        //2.交易表中插入数据;
        Transaction transaction = new Transaction();
        BeanUtils.copyProperties(transferMoneyParam, transaction);
        transaction.setType("TRANSFER");
        transaction.setCreatedAt(new Date());
        transactionMapper.saveMoneyInsertTransaction(transaction); //复用的插入交易记录方法

        //3.账户表中更新源账户的余额from_account_id; 从from里更新余额
        /*DrawMoneyParam drawMoneyParam = new DrawMoneyParam();
        BeanUtils.copyProperties(transferMoneyParam, drawMoneyParam);
        transactionMapper.drawMoneyUpdateTransactionByFromAccountId(drawMoneyParam); //复用方法*/
        accountClient.updateAndGetAccounts(fromAccountId, -amount);

        //4.账户表中更新目标账户的余额to_account_id; 在to账号里 更新添加余额
       /* SaveMoneyParam saveMoneyParam = new SaveMoneyParam();
        BeanUtils.copyProperties(transferMoneyParam, saveMoneyParam);
        transactionMapper.saveMoneyUpdateTransactionByToAccountId(saveMoneyParam); //复用方法*/
        accountClient.updateAndGetAccounts(toAccountId,amount );
    }

    /**
     * 4.查询交易详情
     * @param transactionId 交易id
     * @return
     */
    @Override
    public TransactionDetailVO getTransaction(String transactionId) {
        log.debug("查询交易详情业务:transactionId={}", transactionId);
        TransactionDetailVO transactionDetailVO = transactionMapper.selectTransactionInfoById(transactionId);
        return transactionDetailVO;
    }

    @Override
    public List<Transaction> getAccountTrans(Integer accountId) {
        //select * from transaction where account_id=#{} order by created_at desc

        return transactionMapper.selectTransactionByAccountIdOrderedByCreatedAtDesc(accountId);
    }
}



















